home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / vuser / havefun.c < prev    next >
C/C++ Source or Header  |  1995-06-20  |  8KB  |  372 lines

  1. /* havefun.c - This module contains the code to do the main i/o handling.
  2.  
  3.     Copyright 1989 by Jeffrey F. Lawhorn  (jeffl@berick.uucp)
  4.  
  5.     This file is part of vuser.
  6.  
  7.     vuser is free software; you can redistribute it and/or modify it
  8.     under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 1, or (at your
  10.     option) any later version.
  11.  
  12.     vuser is distributed in the hope that it will be useful, but
  13.     WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.     General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with GNU CC; see the file COPYING.  If not, write to the
  19.     Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #if !defined(lint)
  23. static char SCCSid[] = "$Id: havefun.c,v 1.1 89/12/15 21:28:52 jeffl Exp $";
  24. #endif
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <signal.h>
  29.  
  30. #if defined(__STDC__)
  31. extern void KillSlave();
  32. extern int DeadSlave();
  33. void Send2MasterPty(char *, int);
  34. void Send2stdout(char *, int);
  35. #else
  36. extern void KillSlave();
  37. extern int DeadSlave();
  38. void Send2MasterPty();
  39. void Send2stdout();
  40. #endif
  41.  
  42. extern FILE *ScriptFile;
  43. extern FILE *RecordFile;
  44. extern int MasterPty;
  45. extern int Interactive;
  46.  
  47. char PromptBuf[4096];
  48. char InComingPrompt[8192];
  49. char PromptLookedFor[4096];
  50. int PromptSize = 10;
  51. int PromptCount = 0;
  52. int ICPCount = 0;
  53. int ICPLength = 0;
  54. char *CurrPromptPos = PromptBuf - 1;
  55. char EscapeChar = '@';
  56. #if defined(TIMEOUT_IS_LONG)
  57. long TimeOut = 30;
  58. #else
  59. #include <sys/time.h>
  60. struct timeval TimeOut = {30, 0};
  61. #endif
  62.  
  63. void Send2ScriptFile(curr, start, stop, size)
  64. char *curr, *start, *stop;
  65. int size;
  66. {
  67.     if(curr > stop)
  68.     curr = start + 1;
  69.     while(size--) {
  70.     if(isprint(*curr) && *curr != '\\')
  71.         putc(*curr, ScriptFile);
  72.     else
  73.         switch(*curr) {
  74.         case '\n': fputs("\\n", ScriptFile); break;
  75.         case '\r': fputs("\\r", ScriptFile); break;
  76.         case '\t': fputs("\\t", ScriptFile); break;
  77.         case '\f': fputs("\\f", ScriptFile); break;
  78.         case '\\': fputs("\\\\", ScriptFile); break;
  79.         default: fprintf(ScriptFile, "\\0%03o", *curr); break;
  80.         }
  81.     if(++curr > stop)
  82.         curr = start;
  83.     }
  84.     putc('\n', ScriptFile);
  85.     return;
  86. }
  87.  
  88. int GetOneChar()
  89. {
  90.     char chr = 0;
  91.  
  92.     if(Interactive) {
  93.     write(1, "@", 1);
  94.     read(0, &chr, 1);
  95.     if(chr != EscapeChar)
  96.         write(1, &chr, 1);
  97.     return((int)chr);
  98.     }
  99.     return(getchar());
  100. }
  101.  
  102. int DoEscape(inBuf, cnt)
  103. char *inBuf;
  104. int cnt;
  105. {
  106.     int gotChar = -1;
  107.     char buf[4096];
  108.  
  109.     if(!cnt)
  110.     gotChar = GetOneChar();
  111.     else {
  112.     gotChar = *inBuf++;
  113.     --cnt;
  114.     }
  115.     if(gotChar == EscapeChar) {
  116.     if(ScriptFile) {
  117.         fseek(ScriptFile, -1, 1);
  118.         putc(EscapeChar, ScriptFile);
  119.         putc('\n', ScriptFile);
  120.     }
  121.     if(!Interactive)
  122.         write(1, &gotChar, 1);
  123.     return(0);
  124.     }
  125.     if(Interactive)
  126.     Tty2ShellMode();
  127.     if(gotChar == '!') {
  128.     if(cnt)
  129.         strcpy(buf, inBuf);
  130.     else
  131.         gets(buf);
  132.     if(ScriptFile) {
  133.         fseek(ScriptFile, -1, 1);
  134.         putc('!', ScriptFile);
  135.         fputs(buf, ScriptFile);
  136.     }
  137.     if(!Interactive) {
  138.         write(1, "@!", 2);
  139.         write(1, buf, strlen(buf));
  140.         write(1, "\n", 1);
  141.     }
  142.     signal(SIGCLD, SIG_DFL);
  143.     system(buf);
  144.     signal(SIGCLD, DeadSlave);
  145.     } else if(gotChar == 't' || gotChar == 'T') {
  146.     gets(buf);
  147.     if(ScriptFile) {
  148.         fseek(ScriptFile, -1, 1);
  149.         putc('t', ScriptFile);
  150.         fputs(buf, ScriptFile);
  151.     }
  152.     if(!Interactive) {
  153.         write(1, "@t", 2);
  154.         write(1, buf, strlen(buf));
  155.         write(1, "\n", 1);
  156.     }
  157. #if defined(TIMEOUT_IS_LONG)
  158.     TimeOut = atol(buf);
  159. #else
  160.     TimeOut.tv_sec = atol(buf);
  161. #endif
  162.     } else if(gotChar == 'q' || gotChar == 'Q') {
  163.     gets(buf);
  164.     if(ScriptFile) {
  165.         fseek(ScriptFile, -1, 1);
  166.         putc('q', ScriptFile);
  167.         fputs(buf, ScriptFile);
  168.     }
  169.     if(!Interactive) {
  170.         write(1, "@q", 2);
  171.         write(1, buf, strlen(buf));
  172.         write(1, "\n", 1);
  173.     }
  174.     PromptSize = atoi(buf);
  175.     }
  176.     Tty2ProgramMode();
  177.     return(1);
  178. }
  179.  
  180. void SendResponse();
  181.  
  182. void GetNextPrompt()
  183. {
  184.     int chr = EOF;
  185.  
  186.     ICPLength = 0;
  187.     while((chr = getchar()) != EOF) {
  188.     switch(chr) {
  189.         case '\n': {
  190.         if(!ICPLength)
  191.             SendResponse();
  192.         return;
  193.         }
  194.         case '\\': {
  195.         switch(chr = getchar()) {
  196.             case '0': {
  197.             chr = ((getchar() - '0') * 64);
  198.             chr += ((getchar() - '0') * 8);
  199.             chr += (getchar() - '0');
  200.             break;
  201.             }
  202.             case 'n': chr = '\n'; break;
  203.             case 'r': chr = '\r'; break;
  204.             case 't': chr = '\t'; break;
  205.             case 'f': chr = '\f'; break;
  206.             case '\\': break;
  207.         }
  208.         break;
  209.         }
  210.     }
  211.     PromptLookedFor[ICPLength++] = chr;
  212.     }
  213.     return;
  214. }
  215.  
  216. void SendResponse()
  217. {
  218.     int chr = EOF;
  219.     int sendBufCount = 0;
  220.     char sendBuf[4096];
  221.  
  222.     while((chr = getchar()) != EOF) {
  223.     switch(chr) {
  224.         case '\n': {
  225.         Send2MasterPty(sendBuf, sendBufCount);
  226.         GetNextPrompt();
  227.         return;
  228.         }
  229.         case '\\': {
  230.         switch(chr = getchar()) {
  231.             case '0': {
  232.             chr = ((getchar() - '0') * 64);
  233.             chr += ((getchar() - '0') * 8);
  234.             chr += (getchar() - '0');
  235.             break;
  236.             }
  237.             case 'n': chr = '\n'; break;
  238.             case 'r': chr = '\r'; break;
  239.             case 't': chr = '\t'; break;
  240.             case 'f': chr = '\f'; break;
  241.             case '\\': break;
  242.         }
  243.         break;
  244.         }
  245.     }
  246.     if(chr == EscapeChar)
  247.         if(DoEscape(NULL, 0))
  248.         continue;
  249.     sendBuf[sendBufCount++] = chr;
  250.     }
  251.     return;
  252. }
  253.  
  254. int PromptCompare(ptr1, ptr2, cnt)
  255. char *ptr1, *ptr2;
  256. int cnt;
  257. {
  258.     while(cnt-- && *ptr1++ == *ptr2++);
  259.     if(!cnt)
  260.     return(0);
  261.     return(*--ptr1 - *--ptr2);
  262. }
  263.  
  264. void DoPromptStuff(buf, cnt)
  265. char *buf;
  266. int cnt;
  267. {
  268.     while(cnt--) {
  269.     InComingPrompt[ICPCount++] = *buf++;
  270.     if(ICPCount >= ICPLength) {
  271.         if(ICPCount > 8192) {
  272.         memcpy(InComingPrompt, InComingPrompt + ICPCount - ICPLength,
  273.                ICPLength);
  274.         ICPCount = ICPLength;
  275.         }
  276.         if(!PromptCompare(InComingPrompt + ICPCount - ICPLength,
  277.                   PromptLookedFor, ICPLength)) {
  278.         SendResponse();
  279.         ICPCount = 0;
  280.         continue;
  281.         }
  282.     }
  283.     }
  284.     return;
  285. }
  286.  
  287. void Send2stdout(buf, cnt)
  288. char *buf;
  289. int cnt;
  290. {
  291.     int savedCnt = 0;
  292.     
  293.     if(ScriptFile)
  294.     for(; savedCnt < cnt; ++savedCnt) {
  295.         if(++CurrPromptPos > PromptBuf + PromptSize)
  296.         CurrPromptPos = PromptBuf;
  297.         *CurrPromptPos = *(buf + savedCnt);
  298.         if(PromptCount++ >= PromptSize)
  299.         PromptCount = PromptSize;
  300.     }
  301.     write(1, buf, cnt);
  302.     if(!Interactive)
  303.     DoPromptStuff(buf, cnt);
  304.     if(RecordFile)
  305.     fwrite(buf, 1, cnt, RecordFile);
  306.     return;
  307. }
  308.  
  309. void Send2MasterPty(buf, cnt)
  310. char *buf;
  311. int cnt;
  312. {
  313.     static int lastCharSent = -1;
  314.  
  315.     if(ScriptFile) {
  316.     if(cnt == 1 && *buf != EscapeChar && PromptCount > 0
  317.        && PromptBuf[PromptCount - 1] == lastCharSent) {
  318.         fseek(ScriptFile, -1, 1);
  319.         Send2ScriptFile(buf, buf, buf + 1, 1);
  320.     } else {
  321.         Send2ScriptFile(PromptCount >= PromptSize ?
  322.                 CurrPromptPos+1:PromptBuf,
  323.                 PromptBuf, PromptBuf + PromptSize, PromptCount);
  324.         CurrPromptPos = PromptBuf - 1;
  325.         PromptCount = 0;
  326.         Send2ScriptFile(buf, buf, buf + cnt, cnt);
  327.     }
  328.     lastCharSent = buf[cnt - 1];
  329.     }
  330.     if(Interactive) {
  331.     int pos = 0;
  332.     for(; pos < cnt; ++pos)
  333.         if(buf[pos] == EscapeChar) {
  334.         write(MasterPty, buf, pos);
  335.         if(DoEscape(buf + pos + 1, cnt - pos - 1))
  336.             return;
  337.         }
  338.     }
  339.     write(MasterPty, buf, cnt);
  340.     return;
  341. }
  342.  
  343. void HaveFun()
  344. {
  345.     int readMask = 0, cnt = -1;
  346.     char buf[4096];
  347.  
  348.     if(!Interactive)
  349.     GetNextPrompt();
  350.     while(1) {
  351.     readMask = (1 << MasterPty) | Interactive;
  352.     if(select(32, &readMask, (int *)NULL, (int *)NULL, &TimeOut) < 0) {
  353.         perror("on select: ");
  354.         KillSlave();
  355.     }
  356.     if(readMask & (1 << MasterPty)) {
  357.         if((cnt = read(MasterPty, buf, sizeof(buf))) < 0) {
  358.         perror("read of master pty: ");
  359.         KillSlave();
  360.         }
  361.         Send2stdout(buf, cnt);
  362.     } else if(readMask & 1) {
  363.         if((cnt = read(0, buf, sizeof(buf))) < 0) {
  364.         perror("read of stdin: ");
  365.         KillSlave();
  366.         }
  367.         Send2MasterPty(buf, cnt);
  368.     } else if(!Interactive)
  369.         SendResponse();
  370.     }
  371. }
  372.